package consumer.util;

import com.google.protobuf.ByteString;
import common.proto.JSONUtil;
import common.proto.RPCProtoParamOuterClass;
import common.proto.RPCProtoReqOuterClass;
import consumer.handler.RpcHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.epoll.EpollChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioChannelOption;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.channel.unix.PreferredDirectByteBufAllocator;
import io.netty.handler.codec.http.*;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.DefaultPromise;
import io.netty.util.concurrent.DefaultThreadFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static consumer.handler.RpcHandler.eventExecutor;

/**
 * @ClassName ClientUtil
 * @Description
 * @Author Jingxiao.Ye
 * @Date 2022/1/3 下午9:15
 * @Version V1.0
 * @Since JDK 11
 */
public class ClientUtil {

    public static Object sendMsg(String url,String className,String methodName,Class[] paramClasses,Object[] params){
        String[] split = url.split(":");
        String host = split[0].trim();
        int port = Integer.parseInt(split[1].trim());
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1,new DefaultThreadFactory("client"));
        DefaultPromise<Object> defaultPromise = new DefaultPromise(eventExecutor);
        try {
            Bootstrap bootstrap = new Bootstrap().group(eventLoopGroup)
                    .option(ChannelOption.SO_REUSEADDR, true)
                    .option(ChannelOption.SO_RCVBUF, 128 * 1024)
                    .option(ChannelOption.SO_KEEPALIVE, false)
                    .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<NioSocketChannel>() {
                        protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                            ChannelPipeline p = nioSocketChannel.pipeline();
                            p.addLast(new HttpClientCodec());
                            p.addLast(new HttpObjectAggregator(1024*1024));
                            p.addLast(new RpcHandler(host,port,className,methodName,paramClasses,params,defaultPromise));
                        }
                    });
            bootstrap.connect(host, port).sync().channel().closeFuture();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            Object res = null;
            try {
                res = defaultPromise.get(3, TimeUnit.SECONDS);
            } catch (InterruptedException | ExecutionException | TimeoutException e) {
                e.printStackTrace();
            }finally {
                eventLoopGroup.shutdownGracefully();
            }
            return res;
        }
    }
}
